home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-03 | 62.3 KB | 2,157 lines | [TEXT/MPS ] |
- //----------------------------------------------------------------------------------------
- // UMenuMgr.cp
- // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
- //----------------------------------------------------------------------------------------
-
- //----------------------------------------------------------------------------------------
- // Theory of Operation
- //
- // This unit provides two features: It implements a command numbering system that is
- // independent of menu/ item placement, and implements a framework for optimizing menu
- // setups. The command numbering system works by assigning commands a unique command
- // number, and providing a mechanism for mapping command numbers to menu/ item pairs. A
- // set of routines are provide to manipulate commands via their command number rather
- // than their menu and item numbers.
- //
- // Each command can be assigned an integer command number from 1 to 32767. To associate a
- // command number with a menu item, menu resources are defined with the 'CMNU' resource
- // type--not the 'MENU' type. The 'CMNU' type is just like the 'MENU' type, with an
- // additional command number field for each menu item. This unit converts the 'CMNU'
- // resource into a 'MENU' dynamically at run time.
- //
- // The items of some menus cannot be determined until run-time. The font menu is an
- // example. In such cases, no command number is assigned by you. Instead, the command
- // number is equal to -(256 * menu + item). The procedure CommandToMenuItem converts a
- // command number to a menu id and item number by the following method:
- //
- // - If the command number is positive, the command table is searched for the number. If
- // it is found, CommandToMenuItem returns the corre- sponding menu id and item
- // number. Otherwise the menu and item are zero.
- //
- // - If the command number is negative, the menu number is the upper eight bits, and the
- // item number the lower eight bits, of the absolute value of the command number. (This
- // implies that menu id's must be <= 127 and item numbers must be <= 255.) The function
- // CommandFromMenuItem converts menu/ items to command numbers by the following method:
- //
- // - If the item number is positive, the command table is search for the given menu/ item
- // pair. If found, the corresponding command number is returned. If not found, the number
- // returned is equal to
- // -(256 * menu + item).
- // - If the item number is negative, the number returned is equal to
- // -item number.
- //
- // Note that CommandToMenuItem and CommandFromMenuItem work regardless of whether the
- // command is actually installed in the menu bar. MacApp takes advantage of this feature
- // by having a set of generic "buzz" commands, whose primary use is to set the name of the
- // Undo command (e.g. 'Undo Drawing').
- //
- // The second feature of this unit is to optimize menu setups (changing the appearance of
- // menus and items). Normally, each call to CheckItem, SetItemStyle and SetCommandIcon in
- // turn calls CalcMenuSize because the width or height of the menu may have changed. If
- // menu setups are done all at one time, then CalcMenuSize can be deferred until the end
- // of the setup process. The procedure PerformMenuSetup implements this mechanism. It relies
- // on the fact that menu setups are done all at once, and that you will call
- // SetCommandName, SetItemStyle and SetCommandIcon instead of SetItem, SetItemStyle and
- // SetCommandIcon. It works only for menus whose id is from 1 to mLastMenu. Menus with IDs
- // greater than mLastMenu are not affected by this scheme.
- //
- // PerformMenuSetup accepts one parameter, a procedure which actually implements the menu
- // appearance changes. SetupMenus performs the following steps:
- //
- // - Before calling your menu setup procedure, StartupMenuSetup is called. It disables all
- // menus and items, remembers the current menu proc and enabled flags of each menu, and
- // sets the MenuProc of each menu to gHNullMenuProc, thereby disabling CalcMenuSize.
- //
- // - Your procedure is called.It in turn calls SetCommandName, SetCmdStyle, SetCommandIcon,
- // Enable, EnableCheck, or a Toolbox routine (provided it isn't SetItem, SetItemStyle or
- // SetCommandIcon).
- //
- // - Menus with at least one enabled item are enabled, CalcMenuSize is called for those
- // menus that need it, each menu's menuproc is restored, and DrawMenuBar is called if the
- // enabled state of any menu changed.
- //----------------------------------------------------------------------------------------
-
- #ifndef __UMENUMGR__
- #include "UMenuMgr.h"
- #endif
-
- // MacApp
-
- #ifndef __GEOMETRY__
- #include "Geometry.h"
- #endif
-
- #if qContainer
- #ifndef __UCONTAINER__
- #include "UContainer.h"
- #endif
-
- #endif
-
- #ifndef __UCOREGLOBALS__
- #include "UCoreGlobals.h"
- #endif
-
- #ifndef __UCOREUTILITIES__
- #include "UCoreUtilities.h"
- #endif
-
- #ifndef __UDISPATCHER__
- #include "UDispatcher.h"
- #endif
-
- #ifndef __UFAILURE__
- #include "UFailure.h"
- #endif
-
- #ifndef __UITERATOR__
- #include "UIterator.h"
- #endif
-
- #ifndef __ULIST__
- #include "UList.h"
- #endif
-
- #ifndef __UMACAPPGLOBALS__
- #include "UMacAppGlobals.h"
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include "UMacAppUtilities.h"
- #endif
-
- #ifndef __UMEMORY__
- #include "UMemory.h"
- #endif
-
- #ifndef __UOBJECT__
- #include "UObject.h"
- #endif
-
- #ifndef __UPATCH__
- #include "UPatch.h"
- #endif
-
- #if qContainer
-
- // CALib
-
- #ifndef _CALIB_
- #include "CALib.h"
- #endif
-
- // OpenDoc
-
- #ifndef SOM_Module_OpenDoc_Commands_defined
- #include "CmdDefs.xh"
- #endif
-
- #endif // qContainer
-
- // Toolbox
-
- #ifndef __BALLOONS__
- #include <Balloons.h>
- #endif
-
- #ifndef __LOWMEM__
- #include <LowMem.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __TRAPS__
- #include <Traps.h>
- #endif
-
- // ANSI
-
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
-
- //----------------------------------------------------------------------------------------
- const Boolean kHierarchical = TRUE;
- const Boolean kNotHierarchical = !kHierarchical;
-
- const Boolean kDoHierarchical = TRUE;
- const Boolean kDontDoHierarchical = !kDoHierarchical;
-
- struct MenuCmdRecord
- {
- CommandNumber theCmdNumber;
- ResNumber theMenuNumber;
- short theItemNumber;
- };
-
- typedef MenuCmdRecord *MenuCmdRecordPtr, ** MenuCmdRecordHandle;
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- static CompareResult TestMenuResIDs(ArrayIndex anItem,
- void* yourDataPtr);
- static CompareResult CmdToMenuItem_TestItem(ArrayIndex anItem,
- void* yourDataPtr);
- static CompareResult TestForMenuID(Handle anItem,
- void* yourDataPtr);
- static char TraceMenuName(CommandNumber aCommand);
- static Boolean IsSetupMenu(MenuRef aMenuRef,
- Boolean isHierarchical);
-
- //----------------------------------------------------------------------------------------
- // TCmdTable:
- //----------------------------------------------------------------------------------------
-
- class TCmdTable : public TSortedDynamicArray
- {
- MA_DECLARE_CLASS;
-
- public:
- virtual ~TCmdTable();
-
- inline void ICmdTable()
- { ISortedDynamicArray(0, sizeof(MenuCmdRecord)); }
-
- virtual CompareResult CompareElements(void* Element1,
- void* Element2);// override
-
- virtual void CommandToMenuItem(CommandNumber theCommand,
- MenuID& menu,
- short& item);
- virtual CommandNumber CommandFromMenuItem(short menu,
- short item);
- // Given a menuID,item # return the appropriate command number.
- // If there is no such command number, return -BOR(((menu) << 8), item).
- // If the item number is <0 then assume that it is a negative command number.
-
- void AddToTable(CommandNumber commandNumber,
- MenuID menuNumber,
- short itemNumber);
-
- void AddNewCmdToTableAndUpdateTable(CommandNumber commandNumber,
- MenuID menuNumber,
- short itemNumber);
- // This adds a menu item/command number after the menus have already been
- // set up, and updates all the tables
-
- void DeleteCmdAndUpdateTable(CommandNumber theMenuItemCommandNumber);
- // This deletes a menu item/command number after the menus have already
- // been set up, and updates all the tables
- };
-
-
- //----------------------------------------------------------------------------------------
- // TMenuTable:
- //----------------------------------------------------------------------------------------
-
- class TMenuTable : public TSortedHandleList
- {
- MA_DECLARE_CLASS;
-
- public:
- virtual ~TMenuTable();
-
- inline void IMenuTable()
- { ISortedHandleList(); }
-
- MenuRef GetMenu(MenuID menuID);
-
- virtual CompareResult Compare(Handle item1,
- Handle item2);// override
- };
-
-
- typedef struct MenuIDRecord
- {
- ResNumber fMenuResID;
- MenuID fMenuID;
- } *MenuIDRecordPtr, ** MenuIDRecordHandle;
-
-
- //----------------------------------------------------------------------------------------
- // TMenuIDList:
- //----------------------------------------------------------------------------------------
-
- class TMenuIDList : public TSortedDynamicArray
- {
- MA_DECLARE_CLASS;
-
- public:
- virtual ~TMenuIDList();
-
- inline void IMenuIDList()
- { ISortedDynamicArray(0, sizeof(MenuIDRecord)); }
-
- virtual CompareResult CompareElements(void* Element1,
- void* Element2);// override
-
- MenuID MenuIDFromResID(ResNumber menuResID);
-
- void AddToTable(ResNumber menuResID,
- MenuID menuID);
- };
-
-
- static Handle pHNullMenuProc; // Handle to NULL menu proc
-
- TCmdTable* gCmdTable; // command numbers and their associated menu
- // and item numbers
-
- TMenuTable* gMenuTable; // list of menus created/managed by MacApp
-
- TMenuIDList* gMenuIDList; // list of menu IDs sorted by resource ID
-
- pascal void NullMenuProc(short message,
- MenuRef aMenuRef,
- CRect& menuRect,
- CPoint hitPt,
- short& whichItem);
-
- //----------------------------------------------------------------------------------------
-
- static Boolean gMenusAreInvalid = TRUE;
- // Used by InvalidateMenus to track whether menus need to be setup.
-
- TMenuBarManager* gMenuBarManager;
-
- #if qDebug
- Boolean gTraceSetupMenus;
- #endif
-
-
- //========================================================================================
- // struct CGetMenuID
- //========================================================================================
-
- struct CGetMenuID
- {
- public:
- // Fields
- ResNumber& menuResID;
- TMenuIDList* theMenuIDList;
-
- // Constructor
- inline CGetMenuID(ResNumber& aMenuResID,
- TMenuIDList* aMenuIDList) :
- menuResID(aMenuResID),
- theMenuIDList(aMenuIDList)
- { }
- };
-
-
- //----------------------------------------------------------------------------------------
- // TestMenuResIDs:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CompareResult TestMenuResIDs(ArrayIndex anItem,
- void* yourDataPtr)
- {
- CompareResult returnVal = kItemEqualCriteria;
-
- CGetMenuID * testInfo = (CGetMenuID *)yourDataPtr;
- ResNumber theMenuResIDitem = ((MenuIDRecordPtr)testInfo->theMenuIDList->ComputeAddress(anItem))->fMenuResID;
-
- if (theMenuResIDitem > testInfo->menuResID)
- returnVal = kItemGreaterThanCriteria;
- else if (theMenuResIDitem < testInfo->menuResID)
- returnVal = kItemLessThanCriteria;
-
- return returnVal;
- }
-
-
- //========================================================================================
- // CLASS TMenuIDList
- //========================================================================================
- #undef Inherited
- #define Inherited TSortedDynamicArray
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TMenuIDList,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TMenuIDList destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TMenuIDList::~TMenuIDList()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuIDList::CompareElements:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CompareResult TMenuIDList::CompareElements(void* Element1,
- void* Element2)// override
- {
- CompareResult returnVal = kItem1EqualItem2;
-
- ResNumber theResNumber1 = ((MenuIDRecordPtr)Element1)->fMenuResID;
- ResNumber theResNumber2 = ((MenuIDRecordPtr)Element2)->fMenuResID;
-
- if (theResNumber1 > theResNumber2)
- returnVal = kItem1GreaterThanItem2;
- else if (theResNumber1 < theResNumber2)
- returnVal = kItem1LessThanItem2;
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuIDList::AddToTable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TMenuIDList::AddToTable(ResNumber menuResID,
- MenuID menuID)
- {
- MenuIDRecord arec;
-
- arec.fMenuResID = menuResID;
- arec.fMenuID = menuID;
-
- InsertElementInOrder((Ptr) & arec);
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuIDList::MenuIDFromResID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- MenuID TMenuIDList::MenuIDFromResID(ResNumber menuResID)
- {
- ArrayIndex index;
- CGetMenuID aCGetMenuID(menuResID, this);
-
- if (DoSearchElement(&TestMenuResIDs, &aCGetMenuID, index))
- {
- MenuIDRecordPtr aMenuIDListPtr = (MenuIDRecordPtr)ComputeAddress(index);
- return aMenuIDListPtr->fMenuID;
- }
-
- return 0;
- }
-
-
- //========================================================================================
- // CLASS TCmdTable
- //========================================================================================
- #undef Inherited
- #define Inherited TSortedDynamicArray
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TCmdTable,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TCmdTable destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TCmdTable::~TCmdTable()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::CompareElements:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CompareResult TCmdTable::CompareElements(void* Element1,
- void* Element2)// override
- {
- CompareResult returnVal = kItem1EqualItem2;
-
- CommandNumber theCommanditem1 = ((MenuCmdRecordPtr)Element1)->theCmdNumber;
- CommandNumber theCommanditem2 = ((MenuCmdRecordPtr)Element2)->theCmdNumber;
-
- if (theCommanditem1 > theCommanditem2)
- returnVal = kItem1GreaterThanItem2;
- else if (theCommanditem1 < theCommanditem2)
- returnVal = kItem1LessThanItem2;
-
- return returnVal;
- }
-
- //--------------------------------------------------------------------------------------------------
-
- class CCmdToMenuItem
- {
- public:
- CommandNumber& theCommand;
- TCmdTable* theCmdTable;
-
- inline CCmdToMenuItem(CommandNumber& aCommand,
- TCmdTable* aCmdTable) :
- theCommand(aCommand),
- theCmdTable(aCmdTable)
- { }
- };
-
- #pragma segment MAMenuRes
- CompareResult CmdToMenuItem_TestItem(ArrayIndex anItem,
- void* yourDataPtr)
- {
- CompareResult returnVal = kItemEqualCriteria;
-
- CCmdToMenuItem * testInfo = (CCmdToMenuItem *)yourDataPtr;
- CommandNumber theCommanditem;
-
- theCommanditem = ((MenuCmdRecordPtr)testInfo->theCmdTable->ComputeAddress(anItem))->theCmdNumber;
-
- if (theCommanditem > testInfo->theCommand)
- returnVal = kItemGreaterThanCriteria;
- else if (theCommanditem < testInfo->theCommand)
- returnVal = kItemLessThanCriteria;
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::CommandToMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TCmdTable::CommandToMenuItem(CommandNumber theCommand,
- MenuID& menu,
- short& item)
- {
- ArrayIndex index = 0;
- MenuCmdRecordPtr aMenuCmdRecordPtr;
- CCmdToMenuItem aCCmdToMenuItem(theCommand, this);
-
- if (theCommand < 0) /* negative commands are mapped not table based */
- {
- menu = (short)((-theCommand) >> 8);
- item = (short)((-theCommand) & 255);
- }
- else
- {
- if (DoSearchElement(&CmdToMenuItem_TestItem, &aCCmdToMenuItem, index))
- {
- do
- {
- index--;
- if (index == 0)
- break;
- aMenuCmdRecordPtr = (MenuCmdRecordPtr)ComputeAddress(index);
- } while (aMenuCmdRecordPtr->theCmdNumber == theCommand);
-
- ++index;
-
- do
- {
- aMenuCmdRecordPtr = (MenuCmdRecordPtr)ComputeAddress(index);
- if (aMenuCmdRecordPtr->theCmdNumber == theCommand)
- {
- menu = aMenuCmdRecordPtr->theMenuNumber;
- item = aMenuCmdRecordPtr->theItemNumber;
- if (::GetMenuHandle(menu) != NULL)
- break;
- }
- ++index;
- } while (aMenuCmdRecordPtr->theCmdNumber == theCommand);
- }
- else // not found
- {
- menu = 0;
- item = 0;
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::CommandFromMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CommandNumber TCmdTable::CommandFromMenuItem(short menu,
- short item)
-
- // Given a menuID/item # return the appropriate command number. if there
- // is no such command number, return -BOR(((menu) << 8), item). If the
- // item number is <0 then assume that it is a negative command number.
- {
- if (item < 0)
- return -item;
- else
- {
- if (item > 0)
- {
- // Search the table linearly.
- for (ArrayIndex i = 1; i <= GetSize(); ++i)
- {
- MenuCmdRecordPtr aMenuCmdRecordPtr = (MenuCmdRecordPtr)ComputeAddress(i);
- if ((menu == aMenuCmdRecordPtr->theMenuNumber) && (item == aMenuCmdRecordPtr->theItemNumber))
- {
- return aMenuCmdRecordPtr->theCmdNumber;
- }
- }
- }
-
- #if qDebugMsg
- if ((menu > 127) || (item > 255))
- {
- fprintf(stderr, "menu : %1d , item : %1d \n", menu, item);
- fprintf(stderr, "Menu/item number is too big for a negative command number!\n");
- ProgramBreak("Try using a negative item number instead.");
- }
- #endif
-
- return -((menu << 8) | item);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::AddToTable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void TCmdTable::AddToTable(CommandNumber commandNumber,
- MenuID menuNumber,
- short itemNumber)
- {
- MenuCmdRecord arec;
-
- if (commandNumber > 0) // Negative numbers are mapped not tabled
- {
- arec.theCmdNumber = commandNumber;
- arec.theMenuNumber = menuNumber;
- arec.theItemNumber = itemNumber;
-
- InsertElementInOrder((Ptr) & arec);
- }
- }
-
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::AddNewCmdToTableAndUpdateTable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TCmdTable::AddNewCmdToTableAndUpdateTable(CommandNumber commandNumber,
- MenuID menuNumber,
- short itemNumber)
- {
- MenuCmdRecord arec;
-
- for (ArrayIndex i = 1; i <= GetSize(); i++)
- {
- GetElementsAt(i, &arec, 1);
-
- if ((arec.theMenuNumber == menuNumber) && (arec.theItemNumber >= itemNumber))
- {
- // If we have found an item in the same menu as we are adding to and it is
- // the same index or greater then bump its itemNumber
- arec.theItemNumber++;
-
- // Write it back out
- ReplaceElementsAt(i, &arec, 1);
- }
- }
-
- // Insert the new menu item
- arec.theCmdNumber = commandNumber;
- arec.theMenuNumber = menuNumber;
- arec.theItemNumber = itemNumber;
-
- InsertElementInOrder((Ptr) & arec);
- }
-
- //----------------------------------------------------------------------------------------
- // TCmdTable::DeleteCmdAndUpdateTable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TCmdTable::DeleteCmdAndUpdateTable(CommandNumber theMenuItemCommandNumber)
- {
- MenuCmdRecord arec;
- short menuNumber;
- short itemNumber;
-
- CommandToMenuItem(theMenuItemCommandNumber, menuNumber, itemNumber);
-
- for (ArrayIndex i = 1; i <= GetSize(); i++)
- {
- GetElementsAt(i, &arec, 1);
-
- if (arec.theMenuNumber == menuNumber)
- {
- if (arec.theItemNumber == itemNumber)
- {
- // Delete the element
- DeleteElementsAt(i, 1);
-
- // Back up one element
- --i;
- }
- else if (arec.theItemNumber > itemNumber)
- {
- // If we have found an item in the same menu as we are deleting from and its
- // index is greater then decrement its itemNumber
- arec.theItemNumber--;
-
- // Write it back out
- ReplaceElementsAt(i, &arec, 1);
- }
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TestForMenuID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- CompareResult TestForMenuID(Handle anItem,
- void* yourDataPtr)
- {
- CompareResult returnVal = kItemEqualCriteria;
-
- MenuID * menuID = (MenuID *)yourDataPtr;
-
- short menuIDitem = (*((MenuRef)anItem))->menuID;
-
- if (menuIDitem > *menuID)
- returnVal = kItemGreaterThanCriteria;
- else if (menuIDitem < *menuID)
- returnVal = kItemLessThanCriteria;
-
- return returnVal;
- }
-
-
- //========================================================================================
- // CLASS TMenuTable
- //========================================================================================
- #undef Inherited
- #define Inherited TSortedHandleList
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TMenuTable,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TMenuTable destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TMenuTable::~TMenuTable()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuTable::GetMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- MenuRef TMenuTable::GetMenu(MenuID menuID)
- {
- ArrayIndex index;
-
- return ((MenuRef)DoSearch(&TestForMenuID, &menuID, index));// discard index
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuTable::Compare:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CompareResult TMenuTable::Compare(Handle item1,
- Handle item2) // override
- {
- CompareResult returnVal = kItem1EqualItem2;
-
- MenuID menuID1 = (*((MenuRef)item1))->menuID;
- MenuID menuID2 = (*((MenuRef)item2))->menuID;
-
- if (menuID1 > menuID2)
- returnVal = kItem1GreaterThanItem2;
- else if (menuID1 < menuID2)
- returnVal = kItem1LessThanItem2;
-
- return returnVal;
- }
-
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- #if qDebugMsg
-
- //----------------------------------------------------------------------------------------
- // TraceMenuName:
- //----------------------------------------------------------------------------------------
- #pragma segment MADebug
-
- char TraceMenuName(CommandNumber aCommand)
- // For debugging purposes only--used to dump the name and number of a command
- {
- CStr255 cmdName;
-
- CommandToName(aCommand, cmdName);
- fprintf(stderr, " %1d [%s],", aCommand, (const char*)cmdName);
- return ' ';
- }
-
- #endif
-
- //----------------------------------------------------------------------------------------
- // InvalidateMenus:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void InvalidateMenus()
- {
- gMenusAreInvalid = TRUE;
- }
-
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=mac68k
- #endif
-
- struct MenuBarRecord
- {
- ResNumber nMenus;
- ResNumber menuResID[1000];
- };
-
- #if PRAGMA_ALIGN_SUPPORTED
- #pragma options align=reset
- #endif
-
- //----------------------------------------------------------------------------------------
- // AddMenuBar:
- //----------------------------------------------------------------------------------------
- typedef MenuBarRecord* MenuBarPtr, ** MenuBarHandle;
-
- void AddMenuBar(ResNumber itsID,
- Boolean isHierarchical)
- {
- short hier = 0;
- MenuBarHandle hmbar;
-
- if (isHierarchical)
- hier = -1;
-
- hmbar = (MenuBarHandle)GetResource('MBAR', itsID);
- if (hmbar)
- {
- for (ResNumber i = 0; i < (*hmbar)->nMenus; ++i)
- {
- ResNumber menuResID = (*hmbar)->menuResID[i];
- MenuID menuID = gMenuIDList->MenuIDFromResID(menuResID);
- if (!::GetMenuHandle(menuID)) // do nothing if it's already in menubar
- {
- MenuRef aMenu = MAGetMenu(menuResID);
- if (aMenu)
- {
- MAInsertMenu(aMenu, menuResID, hier);
-
- // a visible menu needed insertion thus the menubar became invalid
- if (!isHierarchical)
- InvalidateMenuBar();
- }
- }
- }
-
- ReleaseResource((Handle)hmbar);
- // hmbar = NULL;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // GetIndMenu:
- //----------------------------------------------------------------------------------------
-
- MenuRef GetIndMenu(ResNumber itsID,
- ResNumber itsIndex)
- {
- MenuRef theMenu = NULL;
-
- MenuBarHandle hmbar = (MenuBarHandle)GetResource('MBAR', itsID);
- if (hmbar)
- {
- ResNumber menuResID = (*hmbar)->menuResID[itsIndex - 1];
- MenuID menuID = gMenuIDList->MenuIDFromResID(menuResID);
- theMenu = MAGetMenu(menuResID);
- ReleaseResource((Handle)hmbar);
- }
- return theMenu;
- }
-
- //----------------------------------------------------------------------------------------
- // CountMenus:
- //----------------------------------------------------------------------------------------
-
- short CountMenus(ResNumber itsID)
- {
- short numMenus = 0;
-
- MenuBarHandle hmbar = (MenuBarHandle)GetResource('MBAR', itsID);
- if (hmbar)
- {
- numMenus = (*hmbar)->nMenus;
- ReleaseResource((Handle)hmbar);
- }
- return numMenus;
- }
-
- //----------------------------------------------------------------------------------------
- // ValidateMenus:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void ValidateMenus()
- {
- gMenusAreInvalid = FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // MenusHavePendingUpdate:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- Boolean MenusHavePendingUpdate()
- {
- return gMenusAreInvalid;
- }
-
- //----------------------------------------------------------------------------------------
- // InvalidateMenuBar:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void InvalidateMenuBar()
- {
- InvalidateMenus(); // if the menubar is invalidated then the
- // menu items must be also
-
- // Systems have "InvalMenuBar"... use that functionality. The system will redraw
- // the menu bar at the next convenient time.
-
- InvalMenuBar();
- }
-
- //----------------------------------------------------------------------------------------
- // CommandEnabled:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- Boolean CommandEnabled(CommandNumber command)
- {
- Boolean returnVal = FALSE;
-
- MenuID menuNo;
- short itemNo;
- MenuRef theMenu;
-
- theMenu = CommandToComponents(command, menuNo, itemNo);
-
- if (theMenu)
- if ((itemNo > 0) && (itemNo < 32))
- returnVal = ((((*theMenu)->enableFlags >> itemNo) & 0x01) != 0);
- else
- returnVal = TRUE;
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // CommandFromMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CommandNumber CommandFromMenuItem(short menu,
- short item)
- {
- return gCmdTable->CommandFromMenuItem(menu, item);
- }
-
- //----------------------------------------------------------------------------------------
- // CommandToMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void CommandToMenuItem(CommandNumber aCommand,
- MenuID& menu,
- short& item)
- {
- gCmdTable->CommandToMenuItem(aCommand, menu, item);
- }
-
- //----------------------------------------------------------------------------------------
- // CommandToName:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void CommandToName(CommandNumber aCommand,
- CStr255& menuText)
- {
- menuText.Empty();
-
- short anItem;
- ResNumber aMenu;
- MenuRef mHandle = CommandToComponents(aCommand, aMenu, anItem);
- if (mHandle)
- GetMenuItemText(mHandle, anItem, menuText);
- }
-
- //----------------------------------------------------------------------------------------
- // CommandToComponents:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- MenuRef CommandToComponents(CommandNumber command,
- MenuID& menuNo,
- short& itemNo)
- {
- MenuRef returnVal = NULL;
-
- CommandToMenuItem(command, menuNo, itemNo);
- if (menuNo) // was found
- returnVal = MAGetMenuRef(menuNo);
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // Enable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void Enable(CommandNumber aCommand,
- Boolean canDo)
- {
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... Enable(%c%s)\n", TraceMenuName(aCommand), (const char*)gBoolString[canDo]);
- #endif
-
- MenuID menu;
- short item;
-
- MenuRef aMenuRef = CommandToComponents(aCommand, menu, item);
- if (aMenuRef)
- if (canDo)
- EnableItem(aMenuRef, item);
- else
- DisableItem(aMenuRef, item);
- }
-
- //----------------------------------------------------------------------------------------
- // EnableCheck:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void EnableCheck(CommandNumber aCommand,
- Boolean canDo,
- Boolean checkIt)
- {
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... EnableCheck(%c%s, %s)\n", TraceMenuName(aCommand), (const char*)gBoolString[canDo], (const char*)gBoolString[checkIt]);
- #endif
-
- MenuID menu;
- short item;
-
- MenuRef aMenuRef = CommandToComponents(aCommand, menu, item);
- if (aMenuRef)
- {
- if (canDo)
- EnableItem(aMenuRef, item);
- else
- DisableItem(aMenuRef, item);
- CheckItem(aMenuRef, item, checkIt);
- }
- }
-
- //========================================================================================
- // GLOBAL Procedures
- //========================================================================================
- #undef Inherited
-
- //----------------------------------------------------------------------------------------
- // GetResMenu: Allow us to get a menu when it's not available via ::GetMenuHandle.
- //----------------------------------------------------------------------------------------
- MenuRef GetResMenu(ResNumber menuResID)
- {
- MenuRef theMenuRef = NULL;
- FailInfo fi;
-
- short oldResFile = MACurResFile();
-
- Try(fi)
- {
- MAUseResFile(gApplicationRefNum);
- theMenuRef = (MenuRef)GetResource('MENU', menuResID);
- fi.Success();
- }
- else
- {
- MAUseResFile(oldResFile);
- fi.ReSignal();
- }
- MAUseResFile(oldResFile);
-
- return theMenuRef;
- }
-
- //----------------------------------------------------------------------------------------
- // ConvertToMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- MenuRef ConvertToMenu(Handle CMNUHandle)
- {
- MenuRef theMenuRef = NULL;
- Ptr theCMNUPtr;
- Ptr theMENUPtr;
- short i;
- MenuID menuNo;
- short itemNo;
- CommandNumber cmdNo;
- Ptr endPtr;
-
- theMenuRef = (MenuRef)NewPermHandle(GetHandleSize(CMNUHandle));
- LockHandle(CMNUHandle);
- LockHandle((Handle)theMenuRef);
-
- theCMNUPtr = (Ptr)StripLong(*CMNUHandle);
- theMENUPtr = (Ptr)StripLong(*theMenuRef);
- menuNo = *((IntegerPtr)theCMNUPtr);
-
- i = (*((CStr255 *)(theCMNUPtr + 14))).Length() + 15;
- MABlockMove(theCMNUPtr, theMENUPtr, i); // move menu header into MENU resource
- theCMNUPtr = (Ptr)(theCMNUPtr + i);
- theMENUPtr = (Ptr)(theMENUPtr + i);
- itemNo = 0;
- endPtr = (Ptr)(theCMNUPtr + GetHandleSize(CMNUHandle));
- while ((theCMNUPtr < endPtr) && (((*((CStr255 *)theCMNUPtr)).Length()) != 0))
- {
- i = ((*((CStr255 *)theCMNUPtr)).Length()) + 5;
- MABlockMove(theCMNUPtr, theMENUPtr, i); // move menu item data sans command number
- theCMNUPtr = (Ptr)(theCMNUPtr + i);
- theMENUPtr = (Ptr)(theMENUPtr + i);
- if ((((long)theCMNUPtr) & 0x00000001) == 1)// word align
- theCMNUPtr = (Ptr)(theCMNUPtr + 1);
- cmdNo = *((CommandNumberPtr)theCMNUPtr);
- ++itemNo;
- theCMNUPtr = (Ptr)(theCMNUPtr + sizeof(CommandNumber));
-
- gCmdTable->AddToTable(cmdNo, menuNo, itemNo);
- }
-
- (*theMENUPtr) = 0; // termination mark
- ++theMENUPtr;
- Size theMenuSize = (Size)(theMENUPtr - StripLong((*theMenuRef)));
-
- HUnlock(CMNUHandle);
- HUnlock((Handle)theMenuRef);
-
- // Set the handle size AFTER unlocking it ;-)
- SetPermHandleSize((Handle)theMenuRef, theMenuSize);
-
- return theMenuRef;
- }
-
- //----------------------------------------------------------------------------------------
- // InitUMenuMgr:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void InitUMenuMgr()
- {
- short num;
- MenuRef newMenu;
- Handle h;
- short i;
- ResNumber menuResID;
- ResType menuResourceType;
- CStr255 menuResourceName;
-
- // Create the MenuResID -> MenuID translation table
- gMenuIDList = new TMenuIDList;
- gMenuIDList->IMenuIDList();
-
- // Create the command table
- gCmdTable = new TCmdTable;
- gCmdTable->ICmdTable();
-
- // Create the menu table
- gMenuTable = new TMenuTable;
- gMenuTable->IMenuTable();
-
- // initialize all CMNUs with positive id
- num = CountResources('CMNU');
- FailResError();
- for (i = 1; i <= num; ++i)
- {
- Handle aCMNUHandle = GetIndResource('CMNU', i);
- FailNILResource(aCMNUHandle);
- HNoPurge(aCMNUHandle); // If it was purgeable it might squirt away
- GetResInfo(aCMNUHandle, &menuResID, &menuResourceType, menuResourceName);
- short menuID = (*(MenuRef)aCMNUHandle)->menuID;
- if (((*(MenuRef)aCMNUHandle)->menuID) > 0)// not in reserved range
- {
- // load the menudef and store its reference in the menu
- newMenu = ConvertToMenu(aCMNUHandle);
- ReleaseResource(aCMNUHandle); // won't be needing this since it's we have a MENU now
- h = GetResource('MDEF', *((short*)(&(*newMenu)->menuProc)));
- (*newMenu)->menuProc = h;
- //CalcMenuSize(newMenu);
- MAInsertInMenuTable(newMenu, menuResID);
- }
- else
- ReleaseResource(aCMNUHandle); // Goodbye!
- }
-
- // initialize all MENUs with positive id
- num = CountResources('MENU');
- FailResError();
- for (i = 1; i <= num; ++i)
- {
- newMenu = (MenuRef)GetIndResource('MENU', i);
- if (newMenu)
- {
- GetResInfo((Handle)newMenu, &menuResID, &menuResourceType, menuResourceName);
-
- THz itsZone = HandleZone((Handle)newMenu);
- // not a System menu and not in reserved range
- if ((itsZone != SystemZone()) && ((*newMenu)->menuID) > 0)
- {
- // load the menudef and store its reference in the menu
- // h = GetResource('MDEF', (short)(((long)(*newMenu)->menuProc) >> sizeof(short)));
- h = GetResource('MDEF', *((short*)(&(*newMenu)->menuProc)));
- (*newMenu)->menuProc = h;
-
- MAInsertInMenuTable(newMenu, menuResID);
- }
- }
- }
-
- #if !qPowerPC
- // Create the NULL menu proc
- pHNullMenuProc = NewPermHandle(sizeof(JmpInstructionTemplate));
- PatchJmpInstruction(*pHNullMenuProc, (void*)StripLong(NullMenuProc));
- #else
- // Create a MenuDefUPP for PowerPC builds…
- pHNullMenuProc = NewPermHandle(sizeof(RoutineDescriptor));
- RoutineDescriptor aMDEFUPP = BUILD_ROUTINE_DESCRIPTOR(uppMenuDefProcInfo, NullMenuProc);
- ::BlockMove(&aMDEFUPP, *pHNullMenuProc, sizeof(RoutineDescriptor));// leave as BlockMove so cache flushes
- #endif
-
- #if qDebugMsg
- if (cUndo - cEditBase != kSysUndo)
- fprintf(stderr, "Invalid UNDO command number\n");
- if (cCut - cEditBase != kSysCut)
- fprintf(stderr, "Invalid CUT command number\n");
- if (cCopy - cEditBase != kSysCopy)
- fprintf(stderr, "Invalid COPY command number\n");
- if (cPaste - cEditBase != kSysPaste)
- fprintf(stderr, "Invalid PASTE command number\n");
- if (cClear - cEditBase != kSysClear)
- fprintf(stderr, "Invalid CLEAR command number\n");
- #endif
-
- }
-
- //----------------------------------------------------------------------------------------
- // IsManagedMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- Boolean IsManagedMenu(MenuRef theMenu)
- {
- return gMenuTable->GetIdentityItemNo((Handle)theMenu) != kEmptyIndex;
- }
-
- //----------------------------------------------------------------------------------------
- // MAGetMenuRef:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- MenuRef MAGetMenuRef(MenuID menuID)
- {
- MenuRef theMenu = ::GetMenuHandle(menuID); // do this first ... the menu is likely to
- // be in the menubar and more likely of
- // success, hence, faster
-
- if (theMenu == NULL) // Try the menu list
- theMenu = gMenuTable->GetMenu(menuID);
-
- return theMenu;
- }
-
- //----------------------------------------------------------------------------------------
- // MAGetMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- MenuRef MAGetMenu(ResNumber menuResID)
- {
- MenuID menuID = gMenuIDList->MenuIDFromResID(menuResID);
-
- MenuRef theMenu = MAGetMenuRef(menuID); // First see if the menu is resident
-
- if (theMenu == NULL) // darn! Try the resource chain
- theMenu = GetResMenu(menuResID);
-
- return theMenu;
- }
-
- //----------------------------------------------------------------------------------------
- // MAGetNewMBar:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- Handle MAGetNewMBar(ResNumber menuRsrcID)
- {
- MCTableHandle theColorTab;
- Handle itsRsrcHandle;
- SignedByte savedState;
- Handle itsNewMBar;
-
- if (qNeedsColorQD || HasColorQD())
- theColorTab = GetMCInfo();
-
- // make the 'MBAR' resource non-purgeable, so the Toolbox doesn't die
- itsRsrcHandle = GetResource('MBAR', menuRsrcID);
- if (itsRsrcHandle)
- {
- savedState = HGetState(itsRsrcHandle);
- HNoPurge(itsRsrcHandle);
- }
-
- itsNewMBar = GetNewMBar(menuRsrcID);
-
- // restore the 'MBAR' resource
- if (itsRsrcHandle)
- HSetState(itsRsrcHandle, savedState);
-
- if (theColorTab && (qNeedsColorQD || HasColorQD()))
- {
- HLock((Handle)theColorTab);
- SetMCEntries((short)(GetHandleSize((Handle)theColorTab) / sizeof(MCEntry)), (*theColorTab));
- HUnlock((Handle)theColorTab);
- DisposeMCInfo(theColorTab);
- }
-
- return itsNewMBar;
- }
-
- //----------------------------------------------------------------------------------------
- // MAInsertInMenuTable:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void MAInsertInMenuTable(MenuRef theMenu,
- ResNumber menuResID)
- {
- gMenuTable->Insert((Handle)theMenu);
-
- // Add the menu to the translation table
- gMenuIDList->AddToTable(menuResID, (*theMenu)->menuID);
- }
-
- //----------------------------------------------------------------------------------------
- // MAInsertMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void MAInsertMenu(MenuRef theMenu,
- ResNumber menuResID,
- MenuID beforeID)
- {
- MenuCRsrcHandle theColorRsrc;
-
- InsertMenu(theMenu, beforeID);
-
- // Since only GetMenu automatically loads the appropriate color information,
- // and (sigh) since we can only call GetMenu once, and if you call DeleteMenu
- // all the good color stuff goes away (double sigh) we'll have to help out
- // the Menu Manager by doing its job for it
-
- if (qNeedsColorQD || HasColorQD())
- {
- // n.b. This is using the menuID of the menu as a resource ID, which is incorrect
- theColorRsrc = (MenuCRsrcHandle)GetResource('mctb', menuResID);
- if (theColorRsrc)
- {
- HLock((Handle)theColorRsrc);
- SetMCEntries((*theColorRsrc)->numEntries, &((*theColorRsrc)->mcEntryRecs[0]));
- HUnlock((Handle)theColorRsrc);
- ReleaseResource((Handle)theColorRsrc);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // NeedCalcMenuSize:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void NeedCalcMenuSize(MenuRef aMenuRef)
- {
- if ((*aMenuRef)->menuProc == pHNullMenuProc)
- (*aMenuRef)->menuWidth = 0;
- }
-
- //----------------------------------------------------------------------------------------
- // NullMenuProc: a NULL menuProc that is used to inhibit re-calculating the menu's size
- // after each call to EnableItem, CheckItem, etc.
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- pascal void NullMenuProc(short,
- MenuRef aMenuRef,
- CRect& ,
- CPoint,
- short&)
- {
- (*aMenuRef)->menuWidth = 0;
- }
-
- //----------------------------------------------------------------------------------------
- // If hierarchical the range of IDs for applications is restricted. See IM V-236.
- const ResNumber kHierarchicalMin = 0;
- const ResNumber kHierarchicalMax = 235;
-
- //----------------------------------------------------------------------------------------
- // IsSetupMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- Boolean IsSetupMenu(MenuRef aMenuRef,
- Boolean isHierarchical)
- {
- #if qDebug
- if (!IsHandle((Handle)aMenuRef))
- {
- VerboseIsHandle((Handle)aMenuRef);
- ProgramBreak("In IsSetupMenu: not handed a handle.");
- return FALSE;
- }
- #endif
-
- MenuID menuID = (*aMenuRef)->menuID;
-
- if (menuID == mApple)
- return FALSE; // _NEVER_ managed!
-
- #if qDebug
- if (menuID == mDebug)
- return TRUE;
- #endif
-
- if (isHierarchical)
- {
- if ((menuID < kHierarchicalMin) || (menuID > kHierarchicalMax))
- return FALSE; // must be in valid range for hierarchicals
- }
- return ((menuID >= mFirstMenu) && (menuID <= mLastMenu));// Range of managed menus
-
- }
-
- //----------------------------------------------------------------------------------------
- // CSetupMenus:
- //----------------------------------------------------------------------------------------
-
- const short kMaxSetupMenus = mLastMenu + 1;
-
- class CSetupMenus
- {
- public:
- inline CSetupMenus() :
- fCount(0)
- { }
-
- void StartMenuSetup(MenuRef aMenuRef);
- void EndMenuSetup();
-
- protected:
- short fCount;
- MenuRef fMenuRef[kMaxSetupMenus];
- Boolean fEnabled[kMaxSetupMenus];
- Handle fMenuProc[kMaxSetupMenus];
- };
-
- //----------------------------------------------------------------------------------------
- // CSetupMenus::StartMenuSetup:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void CSetupMenus::StartMenuSetup(MenuRef aMenuRef)
- {
- #if qDebug
- if (fCount >= kMaxSetupMenus)
- {
- ProgramBreak("Array overflow: too many setup menus.");
- return;
- }
- #endif
-
- // Remember if the menu itself was enabled.
- // Save the menu's menuproc
- fMenuRef[fCount] = aMenuRef;
- fEnabled[fCount] = (Boolean)((*aMenuRef)->enableFlags & 1);
- fMenuProc[fCount] = (*aMenuRef)->menuProc; // See comment below
- ++fCount;
-
- // Set the menu's menuproc to the NullMenuProc, so that
- // CalcMenuSize is disabled (will do ÇalcMenuSize at end of setup).
- (*aMenuRef)->menuProc = pHNullMenuProc;
-
- // Disable the menu and all of its items.
- (*aMenuRef)->enableFlags = 0;
-
- // Uncheck all items.
- short nItems = CountMItems(aMenuRef);
- for (short item = 1; item <= nItems; ++item)// Make sure we don't check items with sub-menus
- {
- short theCmd;
- GetItemCmd(aMenuRef, item, &theCmd);
- if (theCmd != hMenuCmd)
- CheckItem(aMenuRef, item, FALSE); // moves/purges memory
- }
- }
-
- //----------------------------------------------------------------------------------------
- // CSetupMenus::EndMenuSetup:
- //----------------------------------------------------------------------------------------
-
- void CSetupMenus::EndMenuSetup()
- {
- for (short i = 0; i < fCount; ++i)
- {
- MenuRef aMenuRef = fMenuRef[i];
-
- long newFlags = (*aMenuRef)->enableFlags;
- // If any items are enabled, enable the menu
- if (newFlags != 0)
- {
- newFlags = (1 | newFlags);
- (*aMenuRef)->enableFlags = newFlags;
- }
-
- // If the menu's enabled state changed, we have to draw the menu bar.
- MenuID menuID = (*aMenuRef)->menuID;
- if (((newFlags & 1) == 1) != fEnabled[i])
- InvalidateMenuBar();
-
- // Restore the menuproc.
- (*aMenuRef)->menuProc = fMenuProc[i];
-
- // menuWidth set to 0 by routines that require CalcMenuSize, by
- // calling NeedCalcMenu.
- if (!(*aMenuRef)->menuWidth)
- CalcMenuSize(aMenuRef);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // PerformMenuSetup:
- //----------------------------------------------------------------------------------------
-
- void PerformMenuSetup(MenuSetupType TheMenuSetterUpper,
- void* yourDataPtr)
- {
- CSetupMenus setup;
-
- { // in a block to destroy the iterator
- CMenuIterator iter;
- for (MenuRef item = iter.FirstMenu(); iter.More(); item = (MenuRef)iter.NextMenu())
- if (IsSetupMenu(item, kHierarchical))
- setup.StartMenuSetup(item);
- }
-
- TheMenuSetterUpper(yourDataPtr);
-
- setup.EndMenuSetup();
-
- ValidateMenus();
- }
-
- //----------------------------------------------------------------------------------------
- // SetCommandIcon:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void SetCommandIcon(CommandNumber aCommand,
- Byte menuIcon)
- {
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetCommandIcon(%c%d)\n", TraceMenuName(aCommand), menuIcon);
- #endif
-
- MenuID menuID;
- short item;
-
- MenuRef aMenuRef = CommandToComponents(aCommand, menuID, item);
- if (aMenuRef)
- SetItemIcon(aMenuRef, item, menuIcon);
- }
-
- //----------------------------------------------------------------------------------------
- // SetCommandName:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void SetCommandName(CommandNumber aCommand,
- const CStr255& menuText)
- {
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetCommandName(%c'%s')\n", TraceMenuName(aCommand), menuText);
- #endif
-
- #if qDebug
- if (menuText.IsEmpty())
- ProgramBreak("SetCommandName: empty menuText - may corrupt the menu handle!");
- #endif
-
- MenuID menuID;
- short item;
-
- MenuRef aMenuRef = CommandToComponents(aCommand, menuID, item);
- if (aMenuRef)
- SetMenuItemText(aMenuRef, item, menuText);
- }
-
- //----------------------------------------------------------------------------------------
- // SetIndividualCommandName:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void SetIndividualCommandName(CommandNumber aCommand,
- ResNumber rsrcID,
- short strIndex)
- {
- CStr255 s;
-
- GetIndString(s, rsrcID, strIndex);
- SetCommandName(aCommand, s);
- }
-
- //----------------------------------------------------------------------------------------
- // SetMenuState:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void SetMenuState(CommandNumber aCommand,
- ResNumber rsrcID,
- short falseBuzzItem,
- short trueBuzzItem,
- Boolean stateVariable)
- {
- SetIndividualCommandName(aCommand, rsrcID, stateVariable ? trueBuzzItem : falseBuzzItem);
- }
-
- //----------------------------------------------------------------------------------------
- // SetStyle:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void SetStyle(CommandNumber aCommand,
- /* Style */
- short aStyle)
- {
- #if qDebugMsg
- if (gTraceSetupMenus)
- fprintf(stderr, "..... SetStyle(%c%d)\n", TraceMenuName(aCommand), *((Ptr) & aStyle));
- #endif
-
- MenuID menuID;
- short item;
-
- MenuRef aMenuRef = CommandToComponents(aCommand, menuID, item);
- if (aMenuRef)
- SetItemStyle(aMenuRef, item, aStyle);
- }
-
-
- //----------------------------------------------------------------------------------------
- // MAHiliteMenu:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void MAHiliteMenu(short menuID)
- {
- if (menuID || ::LMGetTheMenu())
- ::HiliteMenu(menuID);
- }
-
- #if qContainer
-
- //----------------------------------------------------------------------------------------
- // MARegisterMenu
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void MARegisterMenu(CACommandID id,
- CommandNumber number)
- {
- MenuID menu;
- short item;
- CommandToMenuItem(number, menu, item);
- if (menu > 0)
- CARegisterCommand(id, menu, 0);
- }
-
- //----------------------------------------------------------------------------------------
- // MARegisterCommand
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void MARegisterCommand(CACommandID id,
- CommandNumber number)
- {
- MenuID menu;
- short item;
- CommandToMenuItem(number, menu, item);
- if ((menu > 0) && (item > 0))
- CARegisterCommand(id, menu, item);
- }
-
- //----------------------------------------------------------------------------------------
- // MA_CAInitMenus
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void MA_CASetSharedMenuBar()
- {
- if (gContainerLib)
- {
- /*
-
- AS OF 12/08/95:
- This requires a modified version of CALib (which has not been reviewed by Tantek)
- to run.
-
- */
-
- MenuHandle theAppleMenu = gMenuTable->GetMenu(mApple);
- MenuHandle theFileMenu = gMenuTable->GetMenu(mDocument);
- MenuHandle theEditMenu = gMenuTable->GetMenu(mOpenDocEdit);
-
- if (theAppleMenu && theFileMenu && theEditMenu)
- {
- //••••not using MAInsertMenu b/c that requires menuResID's
- ::InsertMenu(theAppleMenu, 1);
- ::InsertMenu(theFileMenu, 2);
- ::InsertMenu(theEditMenu, 3);
- }
- #if qDebug
- else
- {
- // P.S. Your Hosed....
- DebugStr("\pMacApp could not retrieve the menu handles from the menu table.");
- }
- #endif
-
- CASetBaseMenuBar(GetMenuBar());
- FailOSErr(CAError());
- }
- }
-
- //----------------------------------------------------------------------------------------
- // MA_CARegisterSharedMenuCommands
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void MA_CARegisterSharedMenuCommands()
- {
-
- // The CA must register a minimum set of menu from the apple, file, edit menus.
- // Apple - About
- // File - kODCommandInsert
- // Edit - Undo, Redo, Cut, Copy, Paste, PasteAs, Clear, SelectAll
-
- MARegisterMenu(kODCommandAppleMenu, cAboutApp);
- MARegisterCommand(kODCommandAbout, cAboutApp);
-
- MARegisterMenu(kODCommandDocumentMenu, cNew);
- MARegisterCommand(kODCommandNew, cNew);
- MARegisterCommand(kODCommandOpenDocument, kODCommandOpenDocument);
- MARegisterCommand(kODCommandOpen, cOpen);
- MARegisterCommand(kODCommandInsert, kODCommandInsert);
- MARegisterCommand(kODCommandClose, cClose);
- MARegisterCommand(kODCommandSave, cSave);
- MARegisterCommand(kODCommandSaveACopy, cSaveCopy);
- MARegisterCommand(kODCommandRevert, cRevert);
- MARegisterCommand(kODCommandDraft, kODCommandDraft);
- MARegisterCommand(kODCommandDocumentInfo, kODCommandDocumentInfo);
- MARegisterCommand(kODCommandPageSetup, cPageSetup);
- MARegisterCommand(kODCommandPrint, cPrint);
-
- MARegisterMenu(kODCommandEditMenu, cUndo);
- MARegisterCommand(kODCommandUndo, cUndo);
- MARegisterCommand(kODCommandRedo, kODCommandRedo);
- MARegisterCommand(kODCommandCut, cCut);
- MARegisterCommand(kODCommandCopy, cCopy);
- MARegisterCommand(kODCommandPaste, cPaste);
- MARegisterCommand(kODCommandPasteAs, kODCommandPasteAs);
- MARegisterCommand(kODCommandClear, cClear);
- MARegisterCommand(kODCommandSelectAll, cSelectAll);
- MARegisterCommand(kODCommandGetPartInfo, kODCommandGetPartInfo);
- MARegisterCommand(kODCommandPreferences, kODCommandPreferences);
- MARegisterCommand(kODCommandViewAsWin, kODCommandViewAsWin);
-
- //••• If the user decided to change Apple,File, or Edit structre, they will
- //need to override this method
- }
- #endif
-
- //========================================================================================
- // CLASS CMenuIterator
- //========================================================================================
- #undef Inherited
- #define Inherited CHandleIterator
-
- //----------------------------------------------------------------------------------------
- // CMenuIterator::CMenuIterator: A simple iterator for menus.
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- CMenuIterator::CMenuIterator() :
- CHandleIterator(gMenuTable, kIterateForward)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CMenuIterator::~CMenuIterator:
- //----------------------------------------------------------------------------------------
- #pragma segment IteratorRes
-
- CMenuIterator::~CMenuIterator()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // CMenuIterator::Advance:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void CMenuIterator::Advance() // override
- {
- CHandleIterator::Advance();
-
- // only point at menus that are in the menulist
- if (More() && !::GetMenuHandle((*(CurrentMenu()))->menuID))
- Advance();
- }
-
-
- //========================================================================================
- // CLASS TMenuBarManager
- //========================================================================================
- #undef Inherited
- #define Inherited TObject
-
- #pragma segment MAInit
- MA_DEFINE_CLASS_M1(TMenuBarManager,
- Inherited);
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager destructor
- //----------------------------------------------------------------------------------------
- #pragma segment MADestructorRes
-
- TMenuBarManager::~TMenuBarManager()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::IMenuBarManager:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- void TMenuBarManager::IMenuBarManager(ResNumber otherMenus)
- {
- const CStr255 kParamText1 = "^0";
-
- IObject();
-
- fDisplayedMenus = kNoResource;
- fPreferredMenuBarID = kNoResource;
- fDisplayedHierMenus = kNoResource;
- fPreferredHierMenuBarID = kNoResource;
- #if qContainer
- fAppMenuBar = NULL;
- #endif
-
-
- // Add in the "other" menus, then clear them from the MenuBar
- AddMenuBar(otherMenus, kNotHierarchical);
- ClearMenuBar();
-
- // Initialize the Apple menu
- MenuRef aMenu = MAGetMenu(mApple);
- if (aMenu)
- AppendResMenu(aMenu, 'DRVR');
-
- // If the "About" item contains the paramtext keystring (^0) then substitute the
- // Application's name
- CStr255 s;
- CommandToName(cAboutApp, s);
- short i = s.Pos(kParamText1);
- if (i)
- {
- CStr255 apName;
-
- gDispatcher->GetApplicationName(apName);
- s.Delete(i, kParamText1.Length());
- s.Insert(apName, i);
- SetCommandName(cAboutApp, s);
- }
-
- #if qContainer
- if (gContainerLib)
- {
- MA_CASetSharedMenuBar();
- MA_CARegisterSharedMenuCommands();
- }
- #endif
-
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::SetPreferredMenuBarID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- void TMenuBarManager::SetPreferredMenuBarID(ResNumber theID)
- {
- fPreferredMenuBarID = theID;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::GetPreferredMenuBarID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- ResNumber TMenuBarManager::GetPreferredMenuBarID()
- {
- return fPreferredMenuBarID;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::SetPreferredHierMenuBarID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- void TMenuBarManager::SetPreferredHierMenuBarID(ResNumber theID)
- {
- fPreferredHierMenuBarID = theID;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::GetPreferredHierMenuBarID:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- ResNumber TMenuBarManager::GetPreferredHierMenuBarID()
- {
- return fPreferredHierMenuBarID;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::InstallPreferredMenus:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- void TMenuBarManager::InstallPreferredMenus()
- {
- if (((fDisplayedMenus != fPreferredMenuBarID) && (fPreferredMenuBarID != kNoResource)) || ((fDisplayedHierMenus != fPreferredHierMenuBarID) && (fPreferredHierMenuBarID != kNoResource)))
- {
- ClearMenuBar();
-
- if (fPreferredMenuBarID != kNoResource)
- {
- AddMenuBar(fPreferredMenuBarID, kNotHierarchical);
- fDisplayedMenus = fPreferredMenuBarID;
- }
- else
- AddMenuBar(fDisplayedMenus, kNotHierarchical);
-
- if (fPreferredHierMenuBarID != kNoResource)
- {
- AddMenuBar(fPreferredHierMenuBarID, kHierarchical);
- fDisplayedHierMenus = fPreferredHierMenuBarID;
- }
- else
- AddMenuBar(fDisplayedHierMenus, kHierarchical);
-
- // We must reinsert the help menus whenever ClearMenuBar is called
- gDispatcher->InstallHelpMenuItems();
-
- #if qContainer
- fAppMenuBar = GetMenuBar();
- #endif
-
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::Reset:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
- void TMenuBarManager::Reset()
- {
- fPreferredMenuBarID = kNoResource;
- fPreferredHierMenuBarID = kNoResource;
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::AddHelpMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TMenuBarManager::AddHelpMenuItem(CStr255 helpText,
- CommandNumber helpCommand)
- {
- MenuRef helpMenu = NULL;
- short newHelpItemNo = 9999;
- const CStr255 kParamText1 = "^0";
- OSErr err = noErr;
-
- // If the help item contains the paramtext keystring (^0) then substitute the
- // Application's name
- short i = helpText.Pos(kParamText1);
- if (i)
- {
- CStr255 apName;
-
- gDispatcher->GetApplicationName(apName);
- helpText.Delete(i, kParamText1.Length());
- helpText.Insert(apName, i);
- }
-
- // Put the help item at the end of the help menu
- err = HMGetHelpMenuHandle(&helpMenu);
-
- // If we have a reference to a menu, insert the help command
- if ((err == noErr) && (helpMenu != NULL))
- {
- short oldMenu;
- short oldItem;
-
- // If the new help item is to be inserted at the end of
- // the list, make sure that its number is correct
- short nHelpItems = CountMItems(helpMenu);
- if (newHelpItemNo > nHelpItems)
- newHelpItemNo = nHelpItems + 1;
-
- // Insert the menu, then change its name. This avoids problems
- // that might occur if the application name included metacharacters
- CStr255 helpStr = "Help";
- InsertMenuItem(helpMenu, helpStr, newHelpItemNo - 1);
- SetMenuItemText(helpMenu, newHelpItemNo, helpText);
-
- // Add the help command number to the command table, but only if it's not already there
- if (CommandToComponents(helpCommand, oldMenu, oldItem) == NULL)
- gCmdTable->AddToTable(helpCommand, (*helpMenu)->menuID, newHelpItemNo);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::AddMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TMenuBarManager::AddMenuItem(const CStr255& theMenuItemText,
- MenuID menuNumber,
- short insertAfterItem,
- CommandNumber theMenuItemCommandNumber)
- {
- short theMenuItem = insertAfterItem;
- MenuRef theMenuRef = MAGetMenuRef(menuNumber);
-
- // If we have a reference to a menu, insert the new menu item
- if ((theMenuRef != NULL) && (theMenuItemText.Length() > 0))
- {
- short oldMenu;
- short oldItem;
- short curNumItems;
-
- // Figure out where to insert the new menu item
- curNumItems = CountMItems(theMenuRef);
- if (theMenuItem > curNumItems)
- theMenuItem = curNumItems + 1;
- else
- // The user passed in where to insert it after so add one to take this into account
- theMenuItem++;
-
- // Insert the menu, then change its name. This avoids problems
- // that might occur if the application name included metacharacters
- // One is subtracted here to take into account insert after item that InsMenuItem does
- ::InsertMenuItem(theMenuRef, (ConstStr255Param)"\ptemp", theMenuItem - 1);
- ::SetMenuItemText(theMenuRef, theMenuItem, theMenuItemText);
-
- // Add the help command number to the command table, but only if it's not already there
- if (CommandToComponents(theMenuItemCommandNumber, oldMenu, oldItem) == NULL)
- gCmdTable->AddNewCmdToTableAndUpdateTable(theMenuItemCommandNumber, (*theMenuRef)->menuID, theMenuItem);
-
- // Make sure the menu is updated
- NeedCalcMenuSize(theMenuRef);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TMenuBarManager::DeleteMenuItem:
- //----------------------------------------------------------------------------------------
- #pragma segment MAMenuRes
-
- void TMenuBarManager::DeleteMenuItem(CommandNumber theMenuItemCommandNumber)
- {
- short theMenuNumber;
- short theItemNumber;
-
- gCmdTable->CommandToMenuItem(theMenuItemCommandNumber, theMenuNumber, theItemNumber);
- if (theMenuNumber)
- {
- MenuRef theMenu = MAGetMenuRef(theMenuNumber);
-
- // Delete the menu item from the menu
- if (theMenu != NULL)
- {
- ::DeleteMenuItem(theMenu, theItemNumber);
-
- // Make sure the menu is updated
- NeedCalcMenuSize(theMenu);
- }
-
- // Delete the command number from the table
- gCmdTable->DeleteCmdAndUpdateTable(theMenuItemCommandNumber);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // UMenuMgr.cp
-
- #pragma segment Inline
-
-